//============================================================================
// Name        : 
// Author      : chuanjiang.zh
// Version     :
// Copyright   : Copyright 2017 100wits.com
// Description : Hello World in C, Ansi-style
//============================================================================

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>

#include "CLog.h"

#include "CHttpServer.h"


#include "AppConfig.h"
#include "TEvent.h"
#include "CLog.h"
#include "Path.h"
#include "BasicMacro.h"
#include "OptionParser.h"
#include "TStringUtil.h"

#include "Version.h"
#include "AppConst.h"
#include "SipServer.h"
#include <signal.h>

#include "Ffmpeg.h"

#include "ConsoleLogger.h"
#include "rutil/Log.hxx"
#include "rutil/Logger.hxx"



static bool s_finished = false;
static bool s_receivedHUP = false;
static comn::Event  s_event;


static void signalHandler(int signo)
{
#ifndef _WIN32
    if(signo == SIGHUP)
    {
    	CLog::info("Received HUP signal, logger reset");
        Log::reset();
        s_receivedHUP = true;
        return;
    }
#endif

    CLog::info("Shutting down\n");

    s_finished = true;
    s_event.post();
}

static void setupSignal(bool isDaemon)
{
#ifdef _WIN32
    signal(SIGINT, signalHandler);
    signal(SIGTERM, signalHandler);
#else
    if (isDaemon)
    {
        daemon(0, 1);
    }

    struct sigaction act, oldact;
    memset(&act, 0, sizeof(struct sigaction));
    act.sa_handler = signalHandler;
    sigemptyset(&act.sa_mask);
    sigaddset(&act.sa_mask, SIGALRM);
    sigaddset(&act.sa_mask, SIGINT);
    sigaddset(&act.sa_mask, SIGTERM);
    sigaddset(&act.sa_mask, SIGTSTP);
    sigaction(SIGALRM, &act, &oldact);
    sigaction(SIGINT, &act, &oldact);
    sigaction(SIGTERM, &act, &oldact);
    sigaction(SIGTSTP, &act, &oldact);
    act.sa_flags = 0;

#endif
}


#ifdef WIN32

#include "ExceptionHandler.h"

LONG WINAPI AppUnhandledExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
{
	RecordExceptionInfo(ExceptionInfo, "main");
	return EXCEPTION_EXECUTE_HANDLER;
}


#endif //

std::string getConfigPath()
{
#ifdef WIN32
	std::string workDir = comn::Path::getWorkDir();
	std::string pathList[] =
	{
		".",
		"../bin",
        "../hkgate",
		workDir
	};

#else
	std::string pathList[] =
	{
		".",
        "/usr/etc/hkgate",
		"/usr/etc",
		"/etc"
	};
#endif //

	return comn::Path::findFile(pathList, ARRAY_SIZE(pathList), "hkgate.conf");
}

std::string getWebroot()
{
	std::string workDir = comn::Path::getWorkDir();
	std::string pathList[] =
	{
		".",
		"..",
		"../../",
		"../bin",
		workDir
	};

	return comn::Path::findFile(pathList, ARRAY_SIZE(pathList), "webroot");
}


static ConsoleLogger s_consoleLogger;

void setupLog(bool isDaemon)
{
    if (!isDaemon)
    {
        CLog::setLogger(CLog::COUT, CLog::kNone, 0);
    }
    CLog::setLogger(CLog::DEBUGWINDOW, CLog::kNone, 0);
    CLog::setLogger(CLog::FILE);
    CLog::setFileParam(AppConst::LOG_FILE, 10, 2);

	ExternalLogger* extLogger = isDaemon ? NULL : &s_consoleLogger;
	Log::initialize(Log::File,
		Log::Debug,
		"mixer",
		AppConst::SIP_LOG_FILE,
		extLogger);
}

std::string split(std::string& line)
{
    std::string front(line);
    size_t pos = line.find(' ');
    if (pos == std::string::npos)
    {
        line.clear();
    }
    else
    {
        front = line.substr(0, pos);
        line = line.substr(pos + 1);
    }
    return front;
}

void handleCommand(SipServer& server, std::string line)
{
	static std::string recordId = "";
	static std::string businessId = "";

    std::string cmd = split(line);

    std::string device = "28181";

    if (cmd == "start")
    {
    	int duration = 100;
    }
    else if (cmd == "stop")
    {
    }
    else if (cmd == "open")
    {
    }
    else if (cmd == "close")
    {
    }
    else if (cmd == "test")
    {
    	server.test();
    }
}



int main(int argc, char** argv)
{
	SetUnhandledExceptionFilter(AppUnhandledExceptionFilter);

	OptionParser parser;
	parser.setUsage("%prog [option]");
	std::string strVersion = comn::StringUtil::format("%s Version %s\nCopyright (c) 2015, %s",
			APP_NAME, APP_VERSION, APP_VENDOR);
	parser.setVersion(strVersion);
	parser.enableHelp();
	parser.enableVersion();
	parser.addOption('d', "daemon", "run as daemon");

	if (!parser.parse(argc, argv))
	{
		parser.usage();
		return -1;
	}

	if (parser.hasHelpOption())
	{
		parser.usage();
		return 0;
	}

	if (parser.hasVersionOption())
	{
		parser.version();
		return 0;
	}

	bool isDaemon = parser.hasOption("daemon");
	setupSignal(isDaemon);
	setupLog(isDaemon);

	parser.version();

	if (!isDaemon)
	{
		std::cout << "enter q or quit to exit.\n";
		std::cout << ">> ";
	}

	av_register_all();
	avformat_network_init();

	resip::initNetwork();
	//av::CMediaReaderFactory::startup();

	std::string configPath = getConfigPath();
	AppConfig::instance().load(configPath);

	SipServer sipServer;
	sipServer.test();

	if (!sipServer.start())
	{
		CLog::error("failed to start.\n");
		return -1;
	}

	CHttpServer httpServer;
	httpServer.setUserFile(NULL);

	std::string webroot = getWebroot();
	httpServer.setWebRoot(webroot.c_str());

	int httpPort = AppConfig::instance().getInt("Http.Port", 6080);
	httpServer.start(httpPort, &sipServer);

	sipServer.setHttpServer(&httpServer);

	std::string line;
	while (!s_finished)
	{
		if (isDaemon)
		{
			s_event.timedwait(1000);
		}
		else
		{
			std::istream& istrm = std::getline(std::cin, line);
			if (!istrm.good())
			{
				std::cin.clear();
				s_event.timedwait(1000);
				continue;
			}
			else
			{
				std::cout << ">> ";
			}
		}

		if ((line == "q") || (line == "quit"))
		{
			break;
		}
		else
		{
			handleCommand(sipServer, line);
		}

		if(s_receivedHUP)
		{
			s_receivedHUP = false;
		}
	}

	httpServer.stop();

	sipServer.stop();

	return EXIT_SUCCESS;
}


